<template>
  <div id="wrapper">
    <el-steps style="padding:10px;" :active="active">
      <el-step title="准备"></el-step>
      <el-step title="测速"></el-step>
      <el-step title="完成"></el-step>
    </el-steps>
    <!-- 节点配置 -->
    <el-card v-if="this.active === 1" style="padding:10px;" class="box-card">
      <div slot="header" class="clearfix">
        <span>
          <i class="el-icon-edit-outline"></i>准备测试数据
        </span>
        <!-- 操作按钮 -->
        <div class="clearfix" style="float:right;">
          <el-button size="mini" type="danger" @click="reStart">重置</el-button>
        </div>
      </div>
      <el-button type="primary" icon="el-icon-edit" @click="dialogVisible = true">配置测试节点</el-button>
      <el-link
        type="primary"
        @click="dialogVisible = true"
        v-if="nodeData.length !== 0"
        style="margin-left:10px;"
      >待测{{ nodeData.length }}个节点</el-link>
      <el-dialog
        title="配置测试节点"
        :visible.sync="dialogVisible"
        width="50%"
        :before-close="handleClose"
      >
        <!-- 操作按钮 -->
        <div class="clearfix">
          <el-button-group style="float:right;">
            <el-button size="mini" @click="nodeImportClickHandler">导 入</el-button>
            <el-button size="mini" @click="nodeExportClickHandler">导 出</el-button>
            <el-button type="primary" @click="newVisible = true" size="mini">新增</el-button>
          </el-button-group>
        </div>
        <!-- 新增节点弹窗 -->
        <el-dialog
          title="新增节点"
          :modal="false"
          :visible.sync="newVisible"
          width="60%"
          :before-close="handleNewClose"
        >
          <!-- 测试配置信息列表 -->
          <el-form :model="nodeInfo" style="padding:20px 0;" label-width="80px">
            <el-form-item label="名称">
              <el-input v-model="nodeInfo.name" placeholder="输入测试名称"></el-input>
            </el-form-item>
            <el-form-item label="文件地址">
              <el-input v-model="nodeInfo.url" placeholder="输入http地址"></el-input>
            </el-form-item>
            <el-form-item type="number" label="测试次数">
              <el-input v-model="nodeInfo.times" placeholder="输入测试总次数"></el-input>
            </el-form-item>
            <el-form-item label="超时时间">
              <el-input type="number" v-model="nodeInfo.overtime" placeholder="输入超时时间">
                <template slot="append">秒</template>
              </el-input>
            </el-form-item>
          </el-form>
          <span slot="footer" class="dialog-footer">
            <el-button @click="closeNewNode">取 消</el-button>
            <el-button type="primary" @click="onClickNewNodeHandler">确 定</el-button>
          </span>
        </el-dialog>
        <!-- 节点列表-->
        <el-table
          size="mini"
          height="300"
          :data="nodeData"
          stripe
          style="width: 100%;padding:5px 0;"
        >
          <el-table-column sortable prop="name" label="名称"></el-table-column>
          <el-table-column sortable prop="url" label="地址"></el-table-column>
          <el-table-column sortable prop="times" label="测试次数（单）"></el-table-column>
          <el-table-column sortable prop="overtime" label="超时时间"></el-table-column>
          <el-table-column label="操作">
            <template slot-scope="scope">
              <el-button @click="editNode(scope.row)" type="text" size="small">编辑</el-button>
              <el-popconfirm @onConfirm="deleteNode(scope.row)" title="确认删除该节点吗？">
                <el-button
                  style="color:#f00;margin-left:10px;"
                  type="text"
                  size="small"
                  slot="reference"
                >删除</el-button>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <span slot="footer" class="dialog-footer">
          <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
        </span>
      </el-dialog>
      <!-- 测试配置信息列表 -->
      <el-form :model="testConfig" style="padding:20px 0;width:20vw" label-width="80px">
        <el-form-item type="number" label="测试次数">
          <el-input v-model="testConfig.totalTimes" placeholder="输入测试总次数"></el-input>
        </el-form-item>
        <el-form-item label="超时时间">
          <el-input type="number" v-model="testConfig.overtime" placeholder="输入超时时间">
            <template slot="append">秒</template>
          </el-input>
        </el-form-item>
      </el-form>
      <el-button type="success" @click="onStartClickHandler" style="width:100%;">开始测速</el-button>
    </el-card>
    <!-- 进度展示 -->
    <el-card v-if="this.active === 2" style="padding:10px;" class="box-card">
      <div slot="header" class="clearfix">
        <span>
          <i class="el-icon-loading"></i>
          当前测速节点({{ nowStatus.index }}/{{ nodeData.length }})
        </span>
        <el-link
          @click="stopAllClickHandler"
          type="primary"
          style="float: right; padding: 3px 0;width:80px;"
          :disabled="!isCanStopAll"
        >终止测速</el-link>
        <el-link
          @click="skipStepClickHandler"
          style="float: right; padding: 3px 0;width:80px;"
          :disabled="!isCanSkip"
        >跳过本次</el-link>
      </div>
      <div style="padding:3px;">
        <el-row style="padding:8px;">
          <el-col :span="6">名称：{{ nowStatus.name }}（{{ nowStatus.times }}）</el-col>
          <el-col :span="5">总大小：{{ nowStatus.total }}</el-col>
          <el-col :span="5">跳过时间：{{ nowStatus.countdown }}</el-col>
          <el-col :span="8">预计时间：{{ nowStatus.predict }}</el-col>
        </el-row>
        <el-row style="padding:8px;">
          <el-col :span="16">地址：{{ nowStatus.url }}</el-col>
          <el-col :span="8">速度：{{ nowStatus.speed }}</el-col>
        </el-row>
      </div>
      <div style="padding:8px;">
        <el-progress
          :text-inside="true"
          status="success"
          :stroke-width="26"
          :percentage="nowStatus.progress"
        ></el-progress>
      </div>
    </el-card>
    <el-button
      v-if="this.active === 3"
      style="width:100%;margin:20px 0;"
      type="primary"
      @click="backStart"
    >
      <i class="el-icon-refresh"></i>再来一次
    </el-button>
    <div class="clearfix" style="padding:30px;">
      <span style="font-size:20px;font-weight:bold;">测速结果</span>
      <el-link
        type="primary"
        style="float: right; margin: 3px 10px"
        @click="exportAllDataHandler"
      >导出</el-link>
      <el-link type="danger" style="float: right; margin: 3px 10px" @click="clearAllHandler">清空</el-link>
    </div>
    <el-form :inline="true" :model="formInline" style="padding:5px 30px;">
      <el-form-item label="名称">
        <el-input v-model="formInline.name" placeholder="输入名称"></el-input>
      </el-form-item>
      <el-form-item label="测试轮次">
        <el-input style="width:5vw;min-width:100px;" v-model="formInline.times" placeholder="输入轮次"></el-input>
      </el-form-item>
    </el-form>
    <el-table size="mini" :data="resultDataFiltered" stripe style="width: 100%;padding:5px 30px;">
      <el-table-column sortable prop="name" label="名称"></el-table-column>
      <el-table-column sortable prop="times" label="轮次"></el-table-column>
      <el-table-column sortable prop="complete" label="完成度"></el-table-column>
      <el-table-column
        sortable
        prop="predict"
        label="预计时间"
        :formatter="(row, col) => this.timeFormatter(row.predict)"
      ></el-table-column>
      <el-table-column
        sortable
        prop="time"
        label="实际时间"
        :formatter="(row, col) => this.timeFormatter(row.time)"
      ></el-table-column>
      <el-table-column
        sortable
        prop="low"
        label="最低速度"
        :formatter="(row, col) => this.expressFormatter(row.low)"
      ></el-table-column>
      <el-table-column
        sortable
        prop="avg"
        label="平均速度"
        :formatter="(row, col) => this.expressFormatter(row.avg)"
      ></el-table-column>
      <el-table-column
        sortable
        prop="high"
        label="最高速度"
        :formatter="(row, col) => this.expressFormatter(row.high)"
      ></el-table-column>
      <el-table-column sortable prop="result" label="测试结果"></el-table-column>
    </el-table>
  </div>
</template>

<script>
const { dialog } = require("electron").remote;
import { DataImport, DataExport, CsvExport } from "../../util/FileIO";
import { getTime } from "../../util/DateUtil";
import { ipcRenderer } from "electron";
import { parseByteToExpress } from "../../util/UnitUtil";
export default {
  name: "link-test",
  mounted () {
    ipcRenderer.on(
      "setInitvalue",
      (event, { name, times, total, url, index }) => {
        this.nowStatus.name = name;
        this.nowStatus.times = `第${times}次`;
        this.nowStatus.total = parseByteToExpress(total);
        this.nowStatus.url = url;
        this.nowStatus.index = index;
        this.nowStatus.progress = 0;
        this.nowStatus.countdown = '-';
      }
    );
    ipcRenderer.on("setProcess", (event, { progress, speed, predict, countdown }) => {
      this.nowStatus.progress = progress;
      this.nowStatus.countdown =
        countdown && countdown !== '-' ? getTime(Math.floor(countdown)) : '-';
      this.nowStatus.speed =
        speed && speed !== "-" ? `${parseByteToExpress(speed)}/s` : "-";
      this.nowStatus.predict =
        predict && predict !== "-" ? getTime(Math.floor(predict)) : "-";
    });
    ipcRenderer.on("pushResult", (event, info) => {
      this.pushResult(info);
    });
    ipcRenderer.on("onTestOver", (event, info) => {
      this.onTestOver();
    });
    ipcRenderer.on("onSkipOrStop", (event, info) => {
      this.isCanStopAll = true;
      this.isCanSkip = true;
    });
  },
  data () {
    return {
      active: 1,
      dialogVisible: false,
      newVisible: false,
      nodeInfo: {
        id: "",
        name: "",
        url: "",
        times: void 0,
        overtime: void 0
      },
      formInline: {
        name: "",
        times: ""
      },
      testConfig: {
        totalTimes: 1,
        overtime: void 0
      },
      nowStatus: {
        progress: 0,
        times: "-",
        name: "-",
        total: "-",
        url: "-",
        time: "-",
        speed: "-",
        index: "-",
        predict: "-"
      },
      tableData: [],
      nodeData: [],
      isCanSkip: true,
      isCanStopAll: true
    };
  },
  computed: {
    resultDataFiltered () {
      return this.tableData
        .filter(item => {
          if (!this.formInline.name) return true;
          return item.name.indexOf(this.formInline.name) > -1;
        })
        .filter(item => {
          if (!this.formInline.times) return true;
          return item.times.indexOf(this.formInline.times) > -1;
        });
    }
  },
  methods: {
    reStart () {
      this.$confirm("您确定要重置测试数据吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          Object.assign(this.nodeInfo, {
            id: "",
            name: "",
            url: "",
            times: void 0,
            overtime: void 0
          });
          Object.assign(this.formInline, {
            name: "",
            times: ""
          });
          Object.assign(this.nowStatus, {
            progress: 0,
            times: "-",
            name: "-",
            total: "-",
            url: "-",
            time: "-",
            speed: "-",
            index: "-",
            predict: "-"
          });
          this.nodeData.splice(0, this.nodeData.length);
          this.isCanSkip = true;
          this.isCanStopAll = true;
          this.active = 1;
        })
        .catch(() => { });
    },
    backStart () {
      Object.assign(this.nowStatus, {
        progress: 0,
        times: "-",
        name: "-",
        total: "-",
        url: "-",
        time: "-",
        speed: "-",
        index: "-",
        predict: "-"
      });
      this.isCanSkip = true;
      this.isCanStopAll = true;
      this.active = 1;
    },
    deleteNode (nodeInfo) {
      for (let i = 0; i < this.nodeData.length; i++) {
        if (this.nodeData[i].id === nodeInfo.id) {
          this.nodeData.splice(i, 1);
          break;
        }
      }
    },
    editNode (nodeInfo) {
      Object.assign(this.nodeInfo, nodeInfo);
      this.newVisible = true;
    },
    closeNewNode () {
      this.newVisible = false;
      this.nodeInfo.id = "";
      this.nodeInfo.name = "";
      this.nodeInfo.url = "";
      this.nodeInfo.times = void 0;
      this.nodeInfo.overtime = void 0;
    },
    onClickNewNodeHandler () {
      if (!this.nodeInfo.id) {
        this.nodeInfo.id = new Date().valueOf() + "";
        this.nodeData.push({ ...this.nodeInfo });
      } else {
        for (let i = 0; i < this.nodeData.length; i++) {
          if (this.nodeData[i].id === this.nodeInfo.id) {
            Object.assign(this.nodeData[i], this.nodeInfo);
            break;
          }
        }
      }
      this.closeNewNode();
    },
    nodeImportClickHandler () {
      dialog.showOpenDialog(
        {
          title: "导入节点配置",
          //过滤条件
          filters: [{ name: "节点数据", extensions: ["nodeconf"] }]
        },
        res => {
          DataImport(res[0], data => {
            if (!data) this.$message.error("导入失败，请检查文件格式。");
            else {
              this.nodeData.splice(0, this.nodeData.length);
              this.nodeData.push(...data);
            }
          });
        }
      );
    },
    nodeExportClickHandler () {
      dialog.showSaveDialog(
        {
          title: "导出节点配置",
          //过滤条件
          filters: [{ name: "节点数据", extensions: ["nodeconf"] }]
        },
        res => {
          DataExport(res, this.nodeData, err => {
            if (err) this.$message.error("导出失败:" + err);
            else this.$message({ message: "导出成功", type: "success" });
          });
        }
      );
    },
    onTestOver () {
      this.active = 3;
    },
    pushResult ({ name, times, high, low, avg, time, msg, predict, complete }) {
      this.tableData.push({
        name,
        times: "第" + times + "次",
        time,
        low,
        avg,
        high,
        predict,
        complete,
        result: msg
      });
    },
    expressFormatter (spd) {
      return spd && spd !== "-"
        ? `${parseByteToExpress(Math.floor(spd))}/s`
        : "-";
    },
    timeFormatter (tm) {
      return tm && tm !== "-" ? getTime(Math.floor(tm)) : "-";
    },
    startTest () {
      ipcRenderer.send("downloadFileStart", {
        nodeData: this.nodeData,
        testConfig: this.testConfig
      });
    },
    onStartClickHandler () {
      if (this.nodeData.length <= 0) {
        this.$message.error("请配置测试节点");
        return;
      }
      this.active = 2;
      this.startTest();
    },
    skipStepClickHandler () {
      this.isCanSkip = false;
      ipcRenderer.send("skipNow");
    },
    stopAllClickHandler () {
      this.$confirm("您确定要终止运行吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          this.isCanStopAll = false;
          ipcRenderer.send("stopAll");
        })
        .catch(() => { });
    },
    handleClose () {
      this.dialogVisible = false;
    },
    handleNewClose () {
      this.newVisible = false;
    },
    clearAllHandler () {
      this.$confirm("您确定要清空结果吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          this.tableData.splice(0, this.tableData.length);
        })
        .catch(() => { });
    },
    exportAllDataHandler () {
      dialog.showSaveDialog(
        {
          title: "导出结果集",
          //过滤条件
          filters: [{ name: "Excel数据表", extensions: ["csv"] }]
        },
        res => {
          CsvExport(
            res,
            "名称,轮次,完成度,预计时间(s),实际时间(s),最低速度(byte/s),平均速度(byte/s),最高速度(byte/s),测试结果",
            [
              "name",
              "times",
              "complete",
              "predict",
              "time",
              "low",
              "avg",
              "high",
              "result"
            ],
            this.tableData,
            err => {
              if (err) this.$message.error("导出失败:" + err);
              else this.$message({ message: "导出成功", type: "success" });
            }
          );
        }
      );
    }
  }
};
</script>

<style>
.clearfix:after {
  clear: both;
}
.clearfix:before,
.clearfix:after {
  display: table;
  content: '';
}
.item {
  margin-bottom: 18px;
}
</style>
